////////////////////////////////////////////////////////////////////
// File:	Mesh.cpp
// Purpose: Defines the various structures/classes and data needed for
//			a mesh/skinned mesh in game all in a "MeshComponent" namespace
// Author:	Jay Baird
////////////////////////////////////////////////////////////////////

#ifndef MESHCOMPONENTS_H
#define MESHCOMPONENTS_H

#include "../../src/Util/Vector.h"
#include "../../src/Util/Matrix.h"

#include <vector>
#include <string>

namespace MeshComponent {

#define MESH_SPHERE_ID -50

#pragma pack(1)
typedef struct MeshTriangle
{
	unsigned short index[3];

	MeshTriangle(unsigned short i1, unsigned short i2, unsigned short i3)
	{
		index[0] = i1;
		index[1] = i2;
		index[2] = i3;
	}

	MeshTriangle() { memset(index, 0, sizeof(index[0]) * 3); }

	unsigned short operator[]( int i ) const { return *( &index[0] + i ); }
	unsigned short& operator[]( int i ) { return *( &index[0] + i ); }

} Triangle;
#pragma pack()

typedef struct SkinnedMeshFrame
{
	matrix4 local;
	matrix4 world;

	const SkinnedMeshFrame& operator=(const SkinnedMeshFrame& frame) 
	{
		local = frame.local;
		world = frame.world; 
		return *this;
	}

} Frame;

typedef struct SkinnedMeshBone
{
	unsigned childCount;
	int parent;
	unsigned* children;
	std::string name;

	SkinnedMeshBone() : childCount(0), parent(-1), children(0) { }
	~SkinnedMeshBone()
	{
		if(children)
			delete[] children;
		children = NULL;
	}

	const SkinnedMeshBone& operator=(const SkinnedMeshBone& bone) 
	{
		childCount = bone.childCount;
		parent = bone.parent;
		memcpy(children, bone.children, sizeof(unsigned) * childCount);
		name = bone.name;
		return *this;
	}

} Bone;

typedef struct SkinnedMeshInfluence
{
	int boneIndex;
	float weight;

	SkinnedMeshInfluence(int _boneIndex, float _weight) : boneIndex(_boneIndex), weight(_weight) { }
	SkinnedMeshInfluence() : boneIndex(-1), weight(0.0f) { }

} Influence;

typedef enum MeshBufferType
{
	MESH_BUFFER_TYPE_VERTEX = 0,
	MESH_BUFFER_TYPE_NORMAL,
	MESH_BUFFER_TYPE_TEXCOORD,
	MESH_BUFFER_TYPE_INDEX,
	MESH_BUFFER_TYPE_COLOR,
	MESH_BUFFER_TYPE_MAX

} BufferType;

typedef struct MeshBuffer
{
	unsigned buffers[MESH_BUFFER_TYPE_MAX];

	MeshBuffer() { memset(buffers, 0, MESH_BUFFER_TYPE_MAX * sizeof(buffers[0])); }

} Buffer;

namespace QuadData
{
	const static vec3 QuadVertices[] =
	{
		// Frontface, Center
		vec3(-1.0f, -1.0f, 0.0f),
		vec3(1.0, -1.0f, 0.0f),
		vec3(1.0f, 1.0f, 0.0f),
		vec3(-1.0f, 1.0f, 0.0f)
	};

	const static vec2 QuadTexCoords[] =
	{
		//vec2(0.0f, 1.0f),
		//vec2(1.0f, 1.0f),
		//vec2(1.0f, 0.0f),
		//vec2(0.0f, 0.0f)

		vec2(0.0f, 0.0f),
		vec2(1.0f, 0.0f),
		vec2(1.0f, 1.0f),
		vec2(0.0f, 1.0f)
	};

	const static MeshComponent::Triangle QuadTriangles[]=
	{
		Triangle(1, 3, 0),
		Triangle(1, 2, 3)
	};
};

};

#endif